home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 3 / Cream of the Crop 3.iso / comm / wnos5src.zip / DIRUTIL.C < prev    next >
Text File  |  1993-08-09  |  8KB  |  386 lines

  1. /* dirutil.c - MS-DOS directory reading routines
  2.  *
  3.  * Bdale Garbee, N3EUA, Dave Trulli, NN2Z, and Phil Karn, KA9Q
  4.  * Directory sorting by Mike Chepponis, K3MC
  5.  * New version using regs.h by Russell Nelson.
  6.  * Rewritten for Turbo-C 2.0 routines by Phil Karn, KA9Q 25 March 89
  7.  *
  8.  * Changed commas to dots for European use :-) - DB3FL.910216
  9.  *
  10.  */
  11.  
  12. #include <stdio.h>
  13. #include <dir.h>
  14. #include <dos.h>
  15. #include <stdlib.h>
  16. #include <ctype.h>
  17. #include "global.h"
  18. #include "dirutil.h"
  19. #include "commands.h"
  20. #include "files.h"
  21.  
  22. #ifdef    XXX
  23. static int getdir_nosort __ARGS((char *path,int full,FILE *file));
  24. #endif
  25.  
  26. #define REGFILE    (FA_HIDDEN|FA_SYSTEM|FA_DIREC)
  27.  
  28. #define    insert_ptr(list,new)    (new->next = list,list = new)
  29.  
  30. struct dirsort {
  31.     struct dirsort *next;
  32.     struct ffblk de;
  33. };
  34. #define    NULLSORT (struct dirsort *)0
  35.  
  36. /*
  37.  * Return a string with commas every 3 positions.
  38.  * the original string is replace with the string with commas.
  39.  * The caller must be sure that there is enough room for the resultant
  40.  * string.
  41.  *
  42.  * k3mc 4 Dec 87
  43.  *
  44.  * Changed to dots instead of commas for european use - DB3FL.910216
  45.  *
  46.  */
  47. static void near
  48. commas(char *dest)
  49. {
  50.     unsigned cc = (strlen(dest) - 1) % 3 + 1;    /* Tells us when to insert a comma */
  51.  
  52.     /* Make a copy, so we can muck around */
  53.     char *core = strxdup(dest);
  54.     char *src = core;
  55.  
  56.     while(*src != '\0'){
  57.         *dest++ = *src++;
  58.         if( ((--cc) == 0) && *src ) {
  59.             *dest++ = '.';
  60.             cc = 3;
  61.         }
  62.     }
  63.     xfree(core);
  64.     *dest = '\0';
  65. }
  66.  
  67. static int near
  68. fncmp(char *a,char *b)
  69. {
  70.     int i;
  71.  
  72.     for(;;){
  73.         if (*a == '.') {
  74.             return -1;
  75.         }
  76.         if (*b == '.') {
  77.             return 1;
  78.         }
  79.         if ((i = *a - *b++) != 0) {
  80.             return i;
  81.         }
  82.         if (!*a++) {
  83.             return -1;
  84.         }
  85.     }
  86. }
  87.  
  88. /* Provide additional information only on DIR */
  89. static void near
  90. print_free_space(FILE *file,int n,int d)
  91. {
  92.     unsigned long free_bytes = 0, total_bytes = 0, bpcl = 0;
  93.     char s_free[15], s_total[15];
  94.     struct dfree dtable;
  95.  
  96.     memset(&dtable,0,sizeof(struct dfree));
  97.  
  98.     /* Find disk free space */
  99.     getdfree(d,&dtable);
  100.  
  101.     bpcl         = dtable.df_bsec  * dtable.df_sclus;
  102.     free_bytes  = dtable.df_avail * bpcl;
  103.     total_bytes = dtable.df_total * bpcl;
  104.  
  105.     sprintf(s_free,"%ld",free_bytes);
  106.     commas(s_free);
  107.     sprintf(s_total,"%ld",total_bytes);
  108.     commas(s_total);
  109.  
  110.     fprintf(file,"%s%d file(s). %s bytes free. Disk size %s bytes.\n",
  111.         (n & 1) ? "\n" : "",n,s_free,s_total);
  112. }
  113.  
  114. static void near
  115. format_fname_full(FILE *file,struct ffblk *sbuf,int full,int n)
  116. {
  117.     char line_buf[50];        /* for long dirlist */
  118.     char cbuf[20];            /* for making line_buf */
  119.  
  120.     strcpy(cbuf,sbuf->ff_name);
  121.  
  122.     if (sbuf->ff_attrib & FA_DIREC) {
  123.         strcat(cbuf, "/");
  124.     }
  125.     if (full) {
  126.         /* Long form, give other info too */
  127.         sprintf(line_buf,"%-13s",cbuf);
  128.  
  129.         if(sbuf->ff_attrib & FA_DIREC) {
  130.             strcat(line_buf,"           ");/* 11 spaces */
  131.         } else {
  132.             sprintf(cbuf,"%ld",sbuf->ff_fsize);
  133.             commas(cbuf);
  134.             sprintf(line_buf+strlen(line_buf),"%10s ",cbuf);
  135.         }
  136.         sprintf(line_buf+strlen(line_buf),"%2d:%02d %2d.%02d.%02d%s",
  137.           (sbuf->ff_ftime >> 11) & 0x1f,    /* hour */
  138.           (sbuf->ff_ftime >> 5) & 0x3f,        /* minute */
  139.           (sbuf->ff_fdate ) & 0x1f,            /* day */
  140.           (sbuf->ff_fdate >> 5) & 0xf,        /* month */
  141.           (sbuf->ff_fdate >> 9) + 80,        /* year */
  142.           (n & 1) ? "  " : "\n");
  143.  
  144.         fputs(line_buf,file);
  145.     } else {
  146.         fprintf(file,"%s\n",cbuf);
  147.     }
  148. }
  149.  
  150. /* find the first or next file and lowercase it. */
  151. static int near
  152. nextname(int command, char *name, struct ffblk *sbuf)
  153. {
  154.     int found = (command == 0) ? findfirst(name,sbuf,REGFILE) : findnext(sbuf);
  155.  
  156.     if((found = found == 0) != 0) {
  157.         strlwr(sbuf->ff_name);
  158.     }
  159.     return found;
  160. }
  161.  
  162. /* fix up the filename so that it contains the proper wildcard set */
  163. static char * near
  164. wildcardize(char *path)
  165. {
  166.     struct ffblk sbuf;
  167.     char ourpath[64];
  168.  
  169.     /* Root directory is a special case */
  170.     if(path == NULLCHAR) {
  171.         path = "/*.*";
  172.     } else {
  173.         int i = strlen(path) - 1;
  174.  
  175.         if(path[i] == '\\' || path[i] == '/') {
  176.             strcat(path,"*.*");
  177.         } else if(path[i] == ':') {
  178.             strcat(path,"/*.*");
  179.         }
  180.     }
  181.     /* if they gave the name of a subdirectory, append \*.* to it */
  182.     if(nextname(0, path, &sbuf)
  183.       && (sbuf.ff_attrib & FA_DIREC)
  184.       && !nextname(1, path, &sbuf)) {
  185.         /* if there isn't enough room, give up -- it's invalid anyway */
  186.         if(strlen(path) + 4 > 63) {
  187.             return path;
  188.         }
  189.         strcpy(ourpath, path);
  190.         strcat(ourpath, "\\*.*");
  191.         return ourpath;
  192.     }
  193.     return path;
  194. }
  195.  
  196. /* Create a directory listing in a temp file and return the resulting file
  197.  * descriptor. If full == 1, give a full listing; else return just a list
  198.  * of names.
  199.  */
  200. FILE *
  201. dir(char *path,int full)
  202. {
  203.     FILE *fp;
  204.  
  205.     if((fp = Tmpfile(0,1)) != NULLFILE) {
  206.         getdir(path,full,fp);
  207.         rewind(fp);
  208.     }
  209.     return fp;
  210. }
  211.  
  212. /* wildcard filename lookup */
  213. int
  214. filedir(char *name,int times,char *ret_str)
  215. {
  216.     static struct ffblk sbuf;
  217.  
  218.     int rval = (times == 0) ? findfirst(name,&sbuf,REGFILE) : findnext(&sbuf);
  219.  
  220.     if(rval == -1) {
  221.         *ret_str = '\0';
  222.     } else {
  223.         strcpy(ret_str,sbuf.ff_name);
  224.     }
  225.     return rval;
  226. }
  227.  
  228. /* do a directory list to the stream full = 0 -> short form, 1 is long */
  229. int
  230. getdir(char *path,int full,FILE *file)
  231. {
  232.     struct ffblk sbuf;
  233.     int command = 0, n = 0, d = 0;
  234.     struct dirsort *head = NULLSORT, *here, *new, *next, *this;
  235.  
  236.     path = wildcardize(path);
  237.  
  238.     for(;;){
  239.         if(!nextname(command,path,&sbuf)) {
  240.             break;
  241.         }
  242.         /* Got first one already... */
  243.         command = 1;
  244.  
  245.         if(sbuf.ff_name[0] == '.') {
  246.             /* drop "." and ".." */
  247.             continue;
  248.         }
  249.         new = mxallocw(sizeof(struct dirsort));
  250.         /* Copy contents of directory entry struct */
  251.         new->de = sbuf;
  252.  
  253.         /* insert it into the list */
  254.         if(!head || fncmp(new->de.ff_name,head->de.ff_name) < 0) {
  255.             insert_ptr(head,new);
  256.         } else {
  257.             for(this = head; this->next != NULLSORT; this = this->next) {
  258.                 if(fncmp(new->de.ff_name, this->next->de.ff_name) < 0) {
  259.                     break;
  260.                 }
  261.             }
  262.             insert_ptr(this->next,new);
  263.         }
  264.     } /* infinite FOR loop */
  265.  
  266.     for (here = head; here; here = here->next) {
  267.         format_fname_full(file,&here->de,full,++n);
  268.     }
  269.     /* Give back all the memory we temporarily needed... */
  270.     for( ; head != NULLSORT; head = next) {
  271.         next = head->next;
  272.         xfree(head);
  273.     }
  274.     if(path[1] == ':') {
  275.         d = (toupper(*path)) - 64;
  276.     }
  277.     if(full) {
  278.         print_free_space(file,n,d);
  279.     }
  280.     return 0;
  281. }
  282.  
  283. /* Change working directory */
  284. int
  285. docd(int argc,char **argv,void *p)
  286. {
  287.     char dirname[MAXPATH], *s;
  288.  
  289.     if(argc < 2) {
  290.         if(getcwd(dirname,MAXPATH) != NULLCHAR) {
  291.             while((s = strchr(dirname,'\\')) != NULLCHAR)
  292.                 *s = '/';
  293.             tprintf("%s\n",dirname);
  294.         }
  295.     } else if(chdir(argv[1]) == -1) {
  296.         tprintf("Can't change to %s: %s\n",argv[1],sys_errlist[errno]);
  297.     }
  298.     return 0;
  299. }
  300.  
  301. /* List directory to console */
  302. int
  303. dodir(int argc,char **argv,void *p)
  304. {
  305.     FILE *fp;
  306.     char *margv[2];
  307.  
  308.     margv[1] = strxdup(__tmpnam(NULL,0));
  309.  
  310.     if((fp = Fopen(margv[1],WRITE_TEXT,0,1)) != NULLFILE) {
  311.         char *path = (argc < 2) ? "*.*" : argv[1];
  312.  
  313.         getdir(path,1,fp);
  314.         Fclose(fp);
  315.         domore(2,margv,p);
  316.         unlink(margv[1]);
  317.     }
  318.     xfree(margv[1]);
  319.     return 0;
  320. }
  321.  
  322. /* Delete file */
  323. int
  324. dodelete(int argc,char **argv,void *p)
  325. {
  326.     if(unlink(argv[1]) == -1) {
  327.         tprintf("Can't delete %s: %s\n",argv[1],sys_errlist[errno]);
  328.     }
  329.     return 0;
  330. }
  331.  
  332. /* Rename file */
  333. int
  334. dorename(int argc,char **argv,void *p)
  335. {
  336.     if(rename(argv[1],argv[2]) == -1) {
  337.         tprintf("Can't rename %s to %s: %s\n",argv[1],argv[2],sys_errlist[errno]);
  338.     }
  339.     return 0;
  340. }
  341.  
  342. /* Create directory */
  343. int
  344. domkd(int argc,char **argv,void *p)
  345. {
  346.     if(mkdir(argv[1]) == -1) {
  347.         tprintf("Can't make %s: %s\n",argv[1],sys_errlist[errno]);
  348.     }
  349.     return 0;
  350. }
  351.  
  352. /* Remove directory */
  353. int
  354. dormd(int argc,char **argv,void *p)
  355. {
  356.     if(rmdir(argv[1]) == -1) {
  357.         tprintf("Can't delete %s: %s\n",argv[1],sys_errlist[errno]);
  358.     }
  359.     return 0;
  360. }
  361.  
  362. #ifdef    XXX
  363. static int
  364. getdir_nosort(path,full,file)
  365. char *path;
  366. int full;
  367. FILE *file;
  368. {
  369.     struct ffblk sbuf;
  370.     int command = 0, n = 0;        /* Number of directory entries */
  371.  
  372.     path = wildcardize(path);
  373.  
  374.     while(nextname(command, path, &sbuf)){
  375.         command = 1;    /* Got first one already... */
  376.         if (sbuf.ff_name[0] == '.')    /* drop "." and ".." */
  377.             continue;
  378.         format_fname_full(file, &sbuf, full, ++n);
  379.     }
  380.     if(full)
  381.         print_free_space(file, n, 0);
  382.     return 0;
  383. }
  384. #endif
  385.  
  386.